package com.xone.xapp;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.widget.Toast;

public class HttpUtils {
	
	protected static final String TAG = "HttpUtils";
	protected static final int TIMEOUT = 30 * 1000;//ms
	protected static HttpClient mHttpClient;
	public static final int SC_OK = HttpStatus.SC_OK;
	public static final int SC_UNAUTHORIZED = HttpStatus.SC_UNAUTHORIZED;
	protected static BasicCookieStore cookieStore = new BasicCookieStore();
	protected static HttpContext localContext = new BasicHttpContext();
	static {
		localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
	}

//	SchemeRegistry schemeRegistry = new SchemeRegistry();
//	schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
//
//	ClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
//	HttpClient httpClient = new DefaultHttpClient(cm);
	
	/**
     * Configures the httpClient to connect to the URL provided.
     */
	public static HttpClient createHttpClient() {
		if (null == mHttpClient) {
			mHttpClient = new DefaultHttpClient();
//            final HttpParams params = mHttpClient.getParams();
            mHttpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
//            HttpConnectionParams.setConnectionTimeout(params, TIMEOUT);
//            HttpConnectionParams.setSoTimeout(params, TIMEOUT);
//            ConnManagerParams.setTimeout(params, TIMEOUT);
		}
		return mHttpClient;
	}
	
	public static Thread runOnBackground(final Runnable runnable) {
		final Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					runnable.run();
				} finally {}
			}
		};
		thread.start();
		return thread;
	}
	
	public interface OnPostSuccessListener<T> {
		public T onSuccess(int status, String result);
	}
	
	public interface onGetSuccessListener<T> {
		public T onSuccess(int status, String result);
	}
	
	public static String getIdCode(String url) {
		String result = null;
		try {
			HttpGet httpget = new HttpGet(url);
			httpget.addHeader("X-Requested-With", "appjson");
			HttpClient client = new DefaultHttpClient();
			client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
			httpget.setHeader("User-Agent", Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
			HttpResponse response = client.execute(httpget, localContext);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
				Header[] headers = response.getHeaders("ID-Code");
				if (headers.length > 0) {
					result = headers[0].getValue();
				}
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {// If the response does not enclose an entity, there is no need to worry about connection release
				entity.consumeContent();
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static Bitmap getCodeImage(String url) {
		Bitmap bitmap = null;
		try {
			HttpGet httpget = new HttpGet(url);
			httpget.addHeader("X-Requested-With", "appjson");
			HttpClient client = new DefaultHttpClient();
			client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
			httpget.setHeader("User-Agent", Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
			HttpResponse response = client.execute(httpget, localContext);
			int statusCode = response.getStatusLine().getStatusCode();
			if (HttpStatus.SC_OK == statusCode) {
				HttpEntity entity = response.getEntity();
				if (entity != null) {// If the response does not enclose an entity, there is no need to worry about connection release
					InputStream is = entity.getContent();
					BufferedInputStream bis = new BufferedInputStream(is);
					bitmap = BitmapFactory.decodeStream(bis);
					bis.close();
					is.close();
					entity.consumeContent();
				}
			}
			return bitmap;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static <T> T httpGet(String url, List<NameValuePair> params, onGetSuccessListener<T> onGetSuccessListener) {
		return httpGet(url, params, onGetSuccessListener, null);
	}
	
	public static <T> T httpGet(String url, List<NameValuePair> params, onGetSuccessListener<T> onGetSuccessListener, Context context) {
		String result = null;
		try {
			if (null != params) {
				url = url + "?" + URLEncodedUtils.format(params, "utf-8");
			}
			HttpGet httpget = new HttpGet(url);// Prepare a request object
			httpget.addHeader("X-Requested-With", "appjson");
			httpget.setHeader("User-Agent", Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
			HttpClient client = new DefaultHttpClient();
			HttpResponse response = client.execute(httpget, localContext);
			if (null != onGetSuccessListener) {
				int statusCode = response.getStatusLine().getStatusCode();
				if (statusCode == HttpStatus.SC_OK) {
					HttpEntity entity = response.getEntity();
					if (entity != null) {// If the response does not enclose an entity, there is no need to worry about connection release
						InputStream instream = entity.getContent();// A Simple JSON Response Read
						result = convertStreamToString(instream);
						instream.close();// now you have the string representation of the HTML request
						entity.consumeContent();
					}
					return onGetSuccessListener.onSuccess(HttpStatus.SC_OK, result);
				} else if (statusCode == HttpStatus.SC_UNAUTHORIZED && null != context) {
					autoLogin(response, context);
					return null;
				} else if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
					Header[] headers = response.getHeaders("ID-Code");
					if (headers.length > 0) {
						result = headers[0].getValue();
					}
					HttpEntity entity = response.getEntity();
					if (entity != null) {
						entity.consumeContent();
					}
					return onGetSuccessListener.onSuccess(HttpStatus.SC_UNAUTHORIZED, result);
				} else {
					return onGetSuccessListener.onSuccess(statusCode, null);
				}
			}
		} catch (Exception e) {
			Log.i(TAG, "IOException when execute httpGet", e);
			e.printStackTrace();
		}
		return null;
	}
	
	protected static void autoLogin(HttpResponse response, Context context) throws IOException {
		String username = ShareUtils.getPrefs(ShareUtils.USERNAME, context);
		String password = ShareUtils.getPrefs(ShareUtils.PASSWROR, context);
		if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
			Header[] headers = response.getHeaders("ID-Code");
			String idcode = null;
			if (headers.length > 0) {
				idcode = headers[0].getValue();
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				entity.consumeContent();
			}
			if (null != idcode) {
				AutoLoginDataTask task = new AutoLoginDataTask(context) {
					@Override
					public void loginOk(JSONObject userMap) {
						Toast.makeText(context, "自动登录成功", Toast.LENGTH_LONG).show();
					}
					@Override
					public void loginFailed(String msg) {
						Toast.makeText(context, "自动登录失败", Toast.LENGTH_LONG).show();
						context.startActivity(new Intent(context, LoginActivity.class));
					}
				};
				task.execute(username, password, idcode);
			}
		} else {
			Log.i("HttpUtils", "No username and password");
		}
	}
	
	public static <T> T httpPost(String url, List<NameValuePair> params, OnPostSuccessListener<T> onPostSuccessListener) {
		return httpPost(url, params, onPostSuccessListener, null);
	}
	
	public static <T> T httpPost(String url, List<NameValuePair> params, OnPostSuccessListener<T> onPostSuccessListener, Context context) {
		HttpEntity entity = null;
		if (null != params) {
	        try {
	            entity = new UrlEncodedFormEntity(params, HTTP.UTF_8);
	        } catch (final UnsupportedEncodingException e) {
	            throw new AssertionError(e);
	        }
		}
		HttpClient client = new DefaultHttpClient();
        HttpPost post = new HttpPost(url);
        post.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
        post.setHeader("User-Agent", Constants.USER_AGENT() + Constants.USER_AGENT_TAG);
        post.addHeader("X-Requested-With", "appjson");
        post.setEntity(entity);
        try {
        	HttpResponse response = client.execute(post, localContext);
        	int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				HttpEntity resEntity = response.getEntity();
				String result = null;
				if (resEntity != null) {// If the response does not enclose an entity, there is no need to worry about connection release
					InputStream instream = resEntity.getContent();// A Simple JSON Response Read
					result = convertStreamToString(instream);
					instream.close();// now you have the string representation of the HTML request
					resEntity.consumeContent();
				}
				return onPostSuccessListener.onSuccess(HttpStatus.SC_OK, result);
			} else if (statusCode == HttpStatus.SC_UNAUTHORIZED && null != context) {
				autoLogin(response, context);
				Log.i("HttpUtils", "Need to login");
				return null;
			}
        	return null;
        } catch (final IOException e) {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "IOException when execute httpPost", e);
            }
            return null;
        } finally {
            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "httpPost completing");
            }
        }
	}
	
	public static String connect(String url) {
		return connect(url, null);
	}
	
	public static String connect(String url, String userAgent) {
		if (null == userAgent) {
			userAgent = Constants.USER_AGENT();
		}
		String result = null;
		try {
			HttpClient httpclient = new DefaultHttpClient();
			httpclient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, userAgent + Constants.USER_AGENT_TAG);
			// Prepare a request object
			HttpGet httpget = new HttpGet(url);
			// Execute the request
			HttpResponse response = httpclient.execute(httpget);
			// Examine the response status
			Log.i("Praeda", response.getStatusLine().toString());
			// Get hold of the response entity
			HttpEntity entity = response.getEntity();
			// If the response does not enclose an entity, there is no need
			// to worry about connection release
			if (entity != null) {
				// A Simple JSON Response Read
				InputStream instream = entity.getContent();
				result = convertStreamToString(instream);
				// now you have the string representation of the HTML request
				instream.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	protected static String convertStreamToString(InputStream is) {
		/*
		 * To convert the InputStream to String we use the
		 * BufferedReader.readLine() method. We iterate until the BufferedReader
		 * return null which means there's no more data to read. Each line will
		 * appended to a StringBuilder and returned as String.
		 */
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();
		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}
}
